﻿/*
 * 2008 (c) ralfoide at gmail com
 * Project: SharpFlow
 * License: GPL
 */

using System;
using System.Text;
using sharpCash.OFXClasses;
using System.Text.RegularExpressions;
using System.IO;
using System.Data;
using Alfray.SharpFlow.Utils;
using System.Collections.Generic;
using System.Collections;

namespace Alfray.SharpFlow.Core {
    /// <summary>
    /// The DataCore is a singleton instance that holds all the core data of the application.
    /// Whenever possible, data is stored here rather than in UI classes.
    /// </summary>
    public class DataCore : ILog {
        /// The main singleton instance
        private static DataCore mSingleton;
        /// The main preferences instance
        private Preferences mPreferences = new Preferences();
        /// The current log buffer
        private StringBuilder mLogBuilder = new StringBuilder();
        /// The OFX request object
        OFXREQUEST mOfxRequest = new OFXREQUEST();
        /// The FI list
        FIList mFIList = new FIList();

        /// <summary>
        /// Arguments to the log event, as received by log listeners.
        /// </summary>
        public class LogEventArgs : EventArgs {
            private string mLogContent;
            public LogEventArgs(string logContent) {
                mLogContent = logContent;
            }

            public string logContent() {
                return mLogContent;
            }
        }

        // Event list of listeners to log events.
        // Log listeners response to changes to the log buffer.
        // Note: event object is null when it has no subscribers
        private event EventHandler<LogEventArgs> mLogListener;

        /// <summary>
        /// Creates or returns the singleton instance.
        /// </summary>
        /// <returns>The DataCore singleton</returns>
        public static DataCore singleton {
            get {
                if (mSingleton == null) mSingleton = new DataCore();
                return mSingleton;
            }
        }

        /// <summary>
        /// Gets the logListener event. Listeners can be added or removed.
        /// Log listeners are notified of changes to the log buffer.
        /// </summary>
        public event EventHandler<LogEventArgs> logListener {
            add { mLogListener += value; }
            remove { mLogListener -= value; }
        }

        /// <summary>
        /// Gets the logger.
        /// </summary>
        public ILog logger {
            get { return this; }
        }

        /// <summary>
        /// Gets the core preferences.
        /// </summary>
        public Preferences preferences {
            get { return mPreferences; }
        }

        /// <summary>
        /// Constructor. Private. Use the singleton getter instead.
        /// </summary>
        private DataCore() {
        }

        #region ILog Members

        /// <summary>
        /// Appends a new message to the log buffer and notifies log listeners.
        /// </summary>
        /// <param name="msg">The message to add. \r\n is added as necessary.</param>
        void ILog.append(string msg, params object[] args) {
            mLogBuilder.Append(String.Format(msg, args));
            if (!msg.EndsWith("\r\n")) mLogBuilder.Append("\r\n");
            if (mLogListener != null) mLogListener(this, new LogEventArgs(mLogBuilder.ToString()));
        }

        #endregion

        /// <summary>
        /// Initializes the bank data.
        /// This is blocking.
        /// </summary>
        public void initializeFIList() {
            if (!mFIList.loadFromSettingsFile()) {
                logger.append("Update OFX Servers...");
                mFIList.loadFromWeb();
                logger.append("Update OFX Servers... saving.");
                mFIList.saveToSettingsFile();
            }
            logger.append("Update OFX Servers - completed, {0} FI found",
                mFIList.list.Count);
        }

        public List<FI> getFIList() {
            return mFIList.list;
        }

        private const string kCurrFIName = "curr_fi_name";
        private const string kCurrFIGuid = "curr_fi_guid";

        /// <summary>
        /// Returns the current FI or null.
        /// </summary>
        public FI getCurrentFI() {
            string fi_name = mPreferences[kCurrFIName];
            string fi_code = mPreferences[kCurrFIGuid];

            if (fi_name != null && fi_code != null) {
                return new FI(fi_name, fi_code);
            } else {
                return null;
            }
        }

        /// <summary>
        /// Sets the current FI. Set to null to remove the current FI.
        /// </summary>
        public void setCurrentFI(FI fi) {
            mPreferences[kCurrFIName] = fi.name;
            mPreferences[kCurrFIGuid] = fi.guid;
        }

        /// <summary>
        /// Loads statement for the given FI
        /// </summary>
        public void loadStatements(FI fi) {
            FIDATA fidata = mOfxRequest.getFIDATA(fi.guid);
        }
    }
}
